package com.googlecode.kipler.syntax.concept;

import com.googlecode.kipler.common.Copyable;

public class CardinalityRestriction extends Concept {

	private InequalityConstructor constructor;

	private int no;

	private Concept concept;

	public CardinalityRestriction(InequalityConstructor constructor, int no,
			Concept concept) {
		super();
		setConstructor(constructor);
		setNo(no);
		setConcept(concept);
	}

	public InequalityConstructor getConstructor() {
		return constructor;
	}

	public void setConstructor(InequalityConstructor constructor) {
		this.constructor = constructor;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public Concept getConcept() {
		return concept;
	}

	public void setConcept(Concept concept) {
		this.concept = concept;
	}

	@Override
	public boolean isNegated() {
		return false;
	}

	@Override
	public Concept toggleNegated() {
		Concept result = this;
		if (getConstructor().equals(InequalityConstructor.AT_MOST)) {
			setConstructor(InequalityConstructor.AT_LEAST);
			no++;
		} else {
			if (getNo() == 0) {
				result = new Bottom();
			} else {
				setConstructor(InequalityConstructor.AT_MOST);
				no--;
			}
		}
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && (obj.getClass().equals(this.getClass()))) {
			CardinalityRestriction other = (CardinalityRestriction) obj;
			return (this.isLeftBiased() == other.isLeftBiased()
					&& this.getConstructor().equals(other.getConstructor())
					&& this.getNo() == other.getNo() && this.getConcept()
					.equals(other.getConcept()));
		}
		return false;
	}

	@Override
	public void accept(ConceptVisitor v) {
		v.visitCardinalityRestriction(this);
	}

	/**
	 * @see Copyable#copy()
	 */
	public QualifiedNoRestriction copy() {
		QualifiedNoRestriction qr = new QualifiedNoRestriction();
		qr.setConstructor(getConstructor());
		qr.setNo(no);
		qr.setConcept(getConcept().copy());
		qr.setLeftBiased(isLeftBiased());
		return qr;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(getConstructor());
		buffer.append("(");
		buffer.append(getNo());
		buffer.append(", ");
		buffer.append(getConcept());
		buffer.append(")");
		return buffer.toString();
	}

	@Override
	public void setLeftBiased(boolean value) {
		super.setLeftBiased(value);
		getConcept().setLeftBiased(value);
	}

	@Override
	public int hashCode() {
		return 17 * 37 + new Boolean(isLeftBiased()).hashCode()
				+ getConstructor().hashCode() + getConcept().hashCode();
	}

}
